Imports System
Imports System.Text
Imports System.Data
Imports System.Collections.Generic

Imports Framework
<CLSCompliant(True)> _
Public Enum ESpeaker
    MikeConnell = 1
    ShaneWillard = 6
End Enum

'Table-Row Class (Customisable half)
Partial Public Class CSpeaker

#Region "Constants"
#End Region

#Region "Constructors (Public)"
    'Default Connection String
    Public Sub New()
        MyBase.New()
    End Sub

    'Alternative Connection String
    Public Sub New(ByVal dataSrc As CDataSrc)
        MyBase.New(dataSrc)
    End Sub

    'Hidden (UI code should use cache instead)
    Protected Friend Sub New([speakerId] As Byte)
        MyBase.New([speakerId])
    End Sub
    Protected Friend Sub New(ByVal dataSrc As CDataSrc, [speakerId] As Byte)
        MyBase.New(dataSrc, [speakerId])
    End Sub
    Protected Friend Sub New(ByVal dataSrc As CDataSrc, ByVal [speakerId] As Byte, ByVal txOrNull As IDbTransaction)
        MyBase.New(dataSrc, [speakerId], txOrNull)
    End Sub
#End Region

#Region "Default Values"
    Protected Overrides Sub InitValues_Custom()
        'm_sampleDateCreated = DateTime.Now
        'm_sampleSortOrder   = 0
    End Sub
#End Region

#Region "Default Connection String"
    Protected Overrides Function DefaultDataSrc() As CDataSrc
        Return CDataSrc.Default
    End Function
#End Region

#Region "Properties - Relationships"
    'Relationships - Foriegn Keys (e.g parent)

    'Relationships - Collections (e.g. children)
    Public ReadOnly Property [Products] As CProductList
        Get
            Return CProduct.Cache.GetBySpeaker1or2Id(Me.SpeakerId)
        End Get
    End Property
    Protected Function Products_(ByVal tx As IDbTransaction) As CProductList   'Only used for cascade deletes
        With New CProduct(DataSrc)
            Return .SelectBySpeakerId(Me.SpeakerId, tx)
        End With
    End Function
#End Region

#Region "Properties - Customisation"
    'Derived/ReadOnly (e.g. xml classes, presentation logic)
    Public ReadOnly Property NameAndCount As String
        Get
            Return CUtilities.NameAndCount(SpeakerName, Products)
        End Get
    End Property
    Public ReadOnly Property NameAndCountActive As String
        Get
            Return CUtilities.NameAndCount(CUtilities.Truncate(SpeakerName, 20), Products.Active)
        End Get
    End Property
    Public ReadOnly Property NameAndCountActive(typeId As Byte) As String
        Get
            If typeId = 0 Then
                Return CUtilities.NameAndCount(CUtilities.Truncate(SpeakerName, 20), Products.Active)
            Else
                Return CUtilities.NameAndCount(CUtilities.Truncate(SpeakerName, 20), Products.Active.GetByTypeId(typeId))
            End If
        End Get
    End Property
    Public ReadOnly Property ActiveCount As Integer
        Get
            Return Products.Active.Sermons.Count
        End Get
    End Property


    Private m_rand As New Random
    Private ReadOnly Property SpeakerImagesUrl As String
        Get
            Return String.Concat("~/images/", SpeakerName, "/")
        End Get
    End Property
    Public Function RandomPhotoUrl(otherwiseUrl As String) As String
        Dim name As String = RandomPhoto
        If String.IsNullOrEmpty(name) Then Return otherwiseUrl
        Return String.Concat(SpeakerImagesUrl, name)
    End Function
    Public Function RandomPhotoUrl(otherwiseUrl As String, seedProductId As Integer) As String
        Dim name As String = RandomPhoto(seedProductId)
        If String.IsNullOrEmpty(name) Then Return otherwiseUrl
        Return String.Concat(SpeakerImagesUrl, name)
    End Function
    Private ReadOnly Property RandomPhoto As String
        Get
            If IsNothing(RandomPhotos) Then Return Nothing
            If RandomPhotos.Count = 0 Then Return Nothing
            Return RandomPhotos(m_rand.Next(0, RandomPhotos.Count - 1))
        End Get
    End Property
    Private ReadOnly Property RandomPhoto(seedProductId As Integer) As String
        Get
            If IsNothing(RandomPhotos) Then Return Nothing
            If RandomPhotos.Count = 0 Then Return Nothing
            Return RandomPhotos(seedProductId Mod RandomPhotos.Count)
        End Get
    End Property
    Private m_randomPhotos As List(Of String) = Nothing
    Private ReadOnly Property RandomPhotos As List(Of String)
        Get
            If IsNothing(m_randomPhotos) Then
                SyncLock (Me)
                    If IsNothing(m_randomPhotos) Then
                        Dim sourceFolder As String = String.Concat(CConfig.DropboxPath, "/photos/", SpeakerName, "/")
                        If Not IO.Directory.Exists(sourceFolder) Then
                            m_randomPhotos = New List(Of String)(0)
                            Return m_randomPhotos
                        End If
                        Dim files As String() = IO.Directory.GetFiles(sourceFolder)

                        m_randomPhotos = New List(Of String)(files.Length)

                        Dim copyToFolder As String = System.Web.HttpContext.Current.Server.MapPath(SpeakerImagesUrl)
                        If Not IO.Directory.Exists(copyToFolder) Then IO.Directory.CreateDirectory(copyToFolder)

                        For Each i As String In files
                            Dim name As String = IO.Path.GetFileName(i)
                            Dim path As String = String.Concat(copyToFolder, name)
                            If Not IO.File.Exists(path) Then
                                IO.File.Copy(i, path)
                            ElseIf New IO.FileInfo(i).Length <> New IO.FileInfo(path).Length Then
                                IO.File.Delete(path)
                                IO.File.Copy(i, path)
                            End If
                            m_randomPhotos.Add(name)
                        Next
                    End If
                End SyncLock
            End If
            Return m_randomPhotos
        End Get
    End Property
#End Region

#Region "Save/Delete Overrides"
    'Can Override MyBase.Save/Delete (e.g. Cascade deletes, or insert related records)
    Public Overrides Sub Delete(ByVal txOrNull As IDbTransaction)
        'Use a transaction if none supplied
        If txOrNull Is Nothing Then
            BulkDelete(Me)
            Exit Sub
        End If

        'Cascade-Delete (all child collections)
        Me.Products_(txOrNull).DeleteAll(txOrNull)

        'Normal Delete
        MyBase.Delete(txOrNull)
    End Sub
#End Region

#Region "Custom Database Queries"
    '(Not normally required for cached classes, use list class for searching etc)
    'For Stored Procs can use: MakeListTyped (matching schema), or DataSrc.ExecuteDataset (reports etc)
    'For Dynamic sql, can use: SelectSum, SelectDistinct, SelectCount, SelectWhere (inherited methods)
#End Region

#Region "Searching (Optional)"
    'For cached classes, custom seach logic resides in static methods on the list class
    ' e.g. CSpeaker.Cache.Search("..")

    'See also the auto-generated methods based on indexes
    ' e.g. CSpeaker.Cache.GetBy...
#End Region

#Region "Caching Details"
    'Cache Key
    Friend Shared CACHE_KEY As String = GetType(CSpeaker).ToString 'TABLE_NAME

    'Cache data
    Private Shared Function LoadCache() As CSpeakerList
        Return New CSpeaker().SelectAll()
    End Function

    'Cache Timeout
    Private Shared Sub SetCache(ByVal value As CSpeakerList)
        If Not IsNothing(value) Then value.Sort()
        CCache.Set(CACHE_KEY, value) 'Optional parameter can override timeout (otherwise uses config-settings, which default to 3hrs)
    End Sub

    'Helper Method
    Private Function CacheGetById(ByVal list As CSpeakerList) As CSpeaker
        Return list.GetById(Me.SpeakerId)
    End Function
#End Region

#Region "Cloning"
    Public Function Clone(ByVal target As CDataSrc, ByVal txOrNull As IDbTransaction) As CSpeaker ', parentId As Integer) As CSpeaker
        'Shallow copy: Copies the immediate record, excluding autogenerated Pks
        Dim copy As New CSpeaker(Me, target)

        'Deep Copy - Child Entities: Cloned children must reference their cloned parent
        'copy.SampleParentId = parentId

        copy.Save(txOrNull)

        'Deep Copy - Parent Entities: Cloned parents also clone their child collections
        'Me.Children.Clone(target, txOrNull, copy.SpeakerId)

        Return copy
    End Function
#End Region

#Region "ToXml"
    Protected Overrides Sub ToXml_Custom(ByVal w As System.Xml.XmlWriter)
        'Store(w, "Example", Me.Example)
    End Sub
#End Region

End Class
